|
SimpleCocoaApp とはSimpleCocoaApp は非常にシンプルなアプリケーションですが、正真正銘のアプリケーションです。SimpleCocoaApp は 20 行にも満たない短いコードから構成されていますが、その中にはさまざまな機能が満載されています。このアプリケーションはたしかにそれほど役に立つ動作を行うわけではありませんが、ラジオボタン、ポップアップメニュー、「ヘルプ」メニュー、ウインドウ処理、ボタンクリック、テキストフィールド入力、および「About」ボックスを処理します。次に、実行中のこのアプリケーションの画面を示します (図 1)。
SimpleCocoaApp では、3 つの異なるカスタムクラスからインスタンス化 (作成) された 3 つのメインオブジェクトを使用します。
次に、それぞれのオブジェクトが相互にどのように動作するかを示します。 Cocoa 環境で動作する大部分のコントロールは、それに関連付けられた「ターゲット」オブジェクトを持ち、そのコントロールがアクティブになるとき、ターゲットオブジェクトには「アクションメッセージ」(メソッド呼び出しに似たメッセージ) が送信されます。画面上でのコントロールの体裁と装置としてのコントロールの機能は Cocoa のインフラストラクチャによって処理されるため、実装する必要があるのは、ターゲットオブジェクトとそれに対応するアクションメッセージのみです。したがって、ここでは次のような相互動作が実行されます。
以下のセクションでは、このアプリケーションを書くプロセスを詳細に検討してみましょう。 Interface Builder で行うセットアップ作業通常、Project Builder で新しい Cocoa アプリケーションを作成した後で最初に行う必要があるのは、MainMenu.nib を開いて、Interface Builder でユーザインタフェースとクラスをデザインすることです。SimpleCocoaApp のコードはすでに完成しているため、単に Project Builder で .pbproj ファイルをダブルクリックしてプロジェクトを開き、左側のファイルリストに表示されている MainMenu.nib をダブルクリックするだけです。MainMenu.nib を開くと、nib ウインドウの「Classes」タブには Hello1、Hello2、および HelloController クラスが表示され、「Instances」タブには Hello1、Hello2、HelloController、および MyWindow のインスタンスが表示されます。SimpleCocoaApp を作成するときに最初に行ったのは、Hello1、Hello2、および HelloController カスタムクラスを作成することでした (「Classes」タブで NSObject のようなクラスが選択されている状態で return キーを押して)。さらに、これらのカスタムクラスのインスタンスを作成した上で、コントロール/ビューをウインドウ (ここでは MyWindow) の所定の位置にドラッグしました。Apple では、ユーザの一貫した使用感を維持するため、開発者が Aqua ユーザインタフェースのガイドラインに準拠することを推奨しています。なお、Aqua ユーザインタフェースの詳細については、このテクニカルノートの末尾に挙げてある関連マニュアルのリンクを参照してください。実際のアプリケーションを開発するときにこの段階に達した場合は、UI とカスタムクラスを接続して、それらが相互にメッセージをやり取りしたり、何かの処理 (値の利用、値の設定、動作の変更など) を実行するように相互に指示できるようにする必要があります。ここでは、Interface Builder のみを使用して、この作業をグラフィカルに実行しますが、実際のアプリケーション開発でもコードにまったく手を加える必要がないことがしばしばあります。Interface Builder を使用すると、インスタンス化されているオブジェクトを次の 2 つの方法のいずれかで接続することができます。
これらの接続のいずれかを確立するには、まずメッセージの送信元となるオブジェクトを control キーを押しながらクリックし、カーソルをメッセージの送信先となるオブジェクトまでドラッグします。これにより、2 つのオブジェクトがグレイの線で結ばれます。この後は、inspector ウインドウでアウトレットとアクションをナビゲートし、「Connect」をクリックして接続を確立することができます。アウトレット接続を確立するためにある方向にドラッグした場合、ターゲット-アクション接続を確立するためにはオブジェクト間を逆方向にドラッグする必要があります。要するに、メッセージが送信される方向に control ドラッグを行うということです。 ハ たとえば、図 2 は、インスタンス化された Hello1 オブジェクト内で、Hello1 の -message3: メソッドに対して表示するテキストを保持することになる NSTextField オブジェクトへの「messageTextField」という名前のアウトレットを接続しているところを示しています。この接続を確立するためには、Hello1 オブジェクトから NSTextField に control ドラッグを行います。これは、プログラムが実行されたときに、Hello1 オブジェクトがこのテキストフィールドにメッセージを送信するためです。
一方、図 3 は、「Say Hello...」ボタンのターゲット-アクション接続をセットアップしているところを示しています。このボタンをクリックすると、アクションメッセージがそのターゲットに送信されるため、メッセージがボタンからターゲットに流れるように、ボタンから Hello1 に向かって control ドラッグを行います。そして、inspector ウインドウで「message1:」というアクションを選択して、「Connect」をクリックします。
ユーザインタフェースをグラフィカルにセットアップする作業にはそれなりの時間がかかりますが、長い目で見れば、純粋なソースコードで同じ作業を行うことを考えれば、はるかに時間の節約になります。この時点でコマンドキーを押しながら R キーを押すと (「File」メニューの「Test Interface」)、コードをまったく必要とすることなく、アプリケーションのユーザインタフェース部分の大部分を実行することができます。つまり、コントロールを動作させ、ボタンをクリックしたり (ただし、カスタムコードオブジェクトに接続されたアクションが呼び出されることはありません)、メニューを表示することなどが可能になります。これらすべては、Cocoa でコードを 1 行も書くことなく、何もせずに手に入れることのできる機能です。 ソースコードに戻る前に実行する必要のある最後のステップは、カスタムクラスに対応したスケルトンヘッダ/ソースファイルを作成することです。このためには、「Classes」タブでカスタムクラスを control クリックして、「Create Files...」を選択します。以上の操作で、ユーザインタフェースのデザイン、カスタムオブジェクトのインスタンス化、およびすべての接続の確立を終えて、独自の機能を実装する SimpleCocoaApp のソースコードに戻ることができます。 Main.m
リスト 1 に示すように、main() について多くを語る必要はありません。大部分の読者は、ここに書かれている通りのものとして main() を理解できるはずです。main() は NSApplication をジャンプスタートさせるだけで、NSApplication がアプリケーションの残りの部分、イベントループ、およびその他すべてを実行します。ここで指摘する価値があるとすれば、SimpleCocoaApp のすべてのコードは Objective-C を使って書かれていますが、Java を使って Cocoa アプリケーションを書くこともでき、しかも大部分のオブジェクト/メソッド名が同じであるという点のみです。
Hello1 および Hello2 オブジェクトHello1 および Hello2 クラスは事実上同じものであり、唯一の違いは、これらのクラスが表示するダイアログに配置されたタイトル文字列が異なる点のみです。ここで Hello1 について説明した内容は Hello2 にも当てはまります。このようにほとんど違いのない 2 つのクラスを用意したのは、コントロールのターゲットをその場で切り替える方法を具体的に示すためです。したがって、「Say Hello...」ボタンをクリックしたときにコードのどの行が実行されるかを確認できるのは実行時のみということになります。 ここでは、Hello1 クラスの実装ファイルである Hello1.m を検討してみましょう。空のメソッドを含むクラススケルトンは Interface Builder によって簡単に生成できますが、メソッドの実装を書く作業はプログラマに委ねられています。Hello1 は、-message1:、-message2:、および -message3: という、実装すべき 3 つのメソッドを持っています。
NSRunAlertPanel() (リスト 2 を参照) はユーザにアラートボックスを表示しますが、パラメータを使って、表示されるアラートボックスの内容を構成することができます。最初のパラメータはアラートタイトルで、2 番目のパラメータはアラートメッセージです。また、それに続く 3 つのパラメータはアラート内に 3 つのボタンを表示します。ボタンのパラメータに NULL を渡すと、対応するボタンがアラートから削除されます。ここでは、NSRunAlertPanel() から返される戻り値については特に詳しく言及しませんが、それがクリックされたボタンを表す整数 (対応する定数があらかじめ定義されています) を返すことに注意する必要があります。
リスト 3 に示すように、-message3: は NSRunAlertPanel() にハードコードされたテキスト行ではなく、messageTextField インスタンス変数がポイントする NSTextField のコンテンツを表示させます。前のセクションでは、SimpleCocoaApp のデザインの一部として、Interface Builder で messageTextField アウトレットを NSTextField コントロールに接続しているため、ここで行っているように、NSTextField の値を取り出すことができます。-stringValue メソッドは、NSTextField のコンテンツを NSString として返します。 HelloController オブジェクトHelloController は、SimpleCocoaApp の背後で実際に「頭脳」として動作するクラスです。HelloController はアプリケーションが起動したときに必要となるすべての処理を実行し、アクションメッセージとターゲットの切り替えを処理して、ヘルプが適切に表示されていることを確認します。これらすべての処理は 3 つの簡潔なメソッドを使用して実行されます。
リスト 5 で実際に重要なのは最後の行です。+stringWithFormat: は、printf 形式のフォーマット文字列とパラメータリストを受け付け、C の sprintf ルーチンの考え方に似た方法で文字列を生成します。ここでは、その戻り値を NSSelectorFromString() 関数に渡します。この関数は、名前が暗示しているように、渡された文字列を「セレクタ」、つまりメソッドの完全な名前/識別子 ("method:withParameter1:parameter2:parameter3:" の形式の) に変換します。この後、セレクタは helloButton の -setAction メソッドに渡され、クリックされたときに helloButton によって呼び出されるアクションを変更します。
helloButton は、ウインドウ上の「Say Hello...」NSButton をポイントするアウトレット (Interface Builder で接続した) です。ここでは、setTarget メソッドを呼び出し、ポップアップメニューで選択されたオブジェクトに従って、ボタンのターゲットを hello1 または hello2 のいずれかに変更します。その結果、将来このボタンがクリックされるときには、新しいターゲットにアクションメッセージが送信されることになります。
リスト 7 のルーチン全体は、Interface Builder で「Help」メニュー項目に対するアクションメソッドとして接続されています。+[NSBundle mainBundle] はアプリケーション独自のバンドルをポイントする NSBundle を返すため、そのバンドルからリソース、ヘルプファイルなどをロードすることができます。ここでは、+[NSBundle mainBundle] を使って、ReadMe ファイルへのパスを検出します。+[NSWorkspace sharedWorkspace] (共有ワークスペースとは、Finder を Cocoa 流に表現したもの) は、このパスとアプリケーション名を組み合わせて使用し、指定されたアプリケーションでそのファイルを開きます。
要約すべて引っくるめても約 15 行のソースコードだけで、ここまで見てきたすべての機能を手に入れることができます。このテクニカルノートを読んだ開発者の今後の課題は、Cocoa のフレームワークをできるかぎり多く学ぶことです。そうすれば、開発者は、すでに Cocoa によって実装されている処理をあらためて自分自身で再実装する必要がなくなります。次に、参考になるマニュアルと、このテクニカルノートで取り上げたサンプルコードへのリンクを示します。
オンラインマニュアルMac OS X Developer Documentation (as well as Adopting Aqua documentation) ファイルのダウンロード
|